Slient Blog

MVP + Retrofit + RxJava 优雅的实现

2017-04-12

推荐大家先看下一个学长的google mvp解读
网上有很多关于mvp的教程,自己也看了好多,人云亦云。所以自己跟着学长的教程总结了一个最适合自己的,传送门

看看分包


其实是按照功能分包,大家可以按照自己的习惯来

Base类

BaseView

1
2
3
4
public interface BaseView{
//可以按照自己的需求添加
}

BaseModel

1
2
3
public interface BaseModel {
//可以按照自己的需求添加
}

BasePresenter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public abstract class BasePresenter<V extends BaseView ,M extends BaseModel>{
private static final String TAG = "BasePresenter";
protected V mView;
protected M mModel;
private CompositeSubscription mSubscription;
protected void attach(V mView,M mModel){
if (this.mView==null){
this.mView=mView;
}
if (this.mModel==null){
this.mModel=mModel;
}
}
protected void addSubscribe(Subscription subscription) {
if (mSubscription == null) {
mSubscription = new CompositeSubscription();
}
mSubscription.add(subscription);
}
protected void deatch() {
if (mView!=null){
mView=null;
Log.e(TAG, "unSubscribe: view null" );
}
if (mSubscription != null && mSubscription.hasSubscriptions()) {
mSubscription.clear();
Log.e(TAG, "unSubscribe: mSubscription null");
}
}
}

因为Presenter中要有View和Model的引用,我们直接在BasePresenter中进行添加,可以减少子类的代码,CompositeSubscription来管理RxJava的订阅事件,便于及时的解除订阅,防止内存泄漏。

BaseFragment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public abstract class BaseMvpFragment<P extends BasePresenter,M extends BaseModel>extends Fragment implements BaseView {
protected P mPresenter;
private M mModel;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view=inflater.inflate(getLayoutId(),container,false);
initChildView(view,savedInstanceState );
if (mPresenter == null) {
mPresenter.attach(this,mModel);
}
fragmentLogic();
return view;
}
//逻辑处理
protected abstract void fragmentLogic();
//初始化View
protected abstract void initChildView(View mView,Bundle b);
//获取布局
protected abstract int getLayoutId();
public void onResume() {
super.onResume();
}
public void onDestroy() {
super.onDestroy();
if (mPresenter!=null){
mPresenter.deatch();
}
}
}

在View中我们要持有一个Presenter,在初始化Presenter的时候,我们要用到Model,所以就有了这样的BaseFragment,在Resume中进行初始化,在Destroy中进行数据的清除,防止内存泄漏

Contract(契约类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface GankContract {
interface View extends BaseView{
void showGank(GankPictureBean mGank);
void showBigImage(String url);
}
interface Model extends BaseModel{
Observable <GankPictureBean>getGank( );
}
abstract class Presenter extends BasePresenter<View,Model>{
public abstract void getGank();
}
}

我们为每一个功能添加一个具体的Contract契约类来管理Model,View,Presenter,因为数据的处理一般是在io线程,所以这个时候我们选择用RxJava讲Model进行封装,方便之后的直接用RxJava进行异步操作

封装网络请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class GankApiService {
private Retrofit mRetrofit;
public static final String BASE_URL="http://gank.io/api/random/data/福利/";
private GankApiService(){
OkHttpClient.Builder mBuilder=new OkHttpClient.Builder()
.writeTimeout(5, TimeUnit.SECONDS);
mRetrofit=new Retrofit.Builder()
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.client(mBuilder.build())
.build();
}
public static GankApiService getInstance(){
return SingleInstance.INSTANVE;
}
private static class SingleInstance{
private static final GankApiService INSTANVE=new GankApiService();
}
public GankApi getGankApi(){
return mRetrofit.create(GankApi.class);
}
}

Retrofit不了解的可以看Retrofit + RxJava Retrofit 2.0

实现类

ModelImp

1
2
3
4
5
6
7
8
9
10
11
12
public class GankModel implements GankContract.Model {
@Override
public Observable<GankPictureBean> getGank() {
return GankApiService.getInstance()
.getGankApi()
.getGank(20)
.subscribeOn(SchedulerProvider.getInstance().io())
.unsubscribeOn(SchedulerProvider.getInstance().io())
.observeOn(SchedulerProvider.getInstance().ui());
}
}

这里的实现是和网络请求的封装结合到一块的。

PresenterImp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class GankPresenter extends GankContract.Presenter {
private static final String TAG = "GankPresenter";
@Override
public void getGank() {
Subscription subscription = mModel.getGank()
.subscribe(new Observer<GankPictureBean>() {
@Override
public void onCompleted() {
Log.i(TAG, "onCompleted: success " );
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError: something wrong");
}
@Override
public void onNext(GankPictureBean gank) {
mView.showGank(gank);
}
});
addSubscribe(subscription);
}
}

因为Base中帮我们做了很好的封装,所以代码中只需要处理逻辑事件,当有订阅事件的时候直接调用addSubscribe方法,便于及时解除订阅

FragmentImp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class GankFragment extends BaseMvpFragment<GankPresenter,GankModel> implements GankContract.View {
private RecyclerView mRecyclerView;
private GankAdapter mGankAdapter;
private List<GankPictureBean.ResultsBean>mGankList;
public static GankFragment getInstance(){
return new GankFragment();
}
@Override
protected void fragmentLogic() {
mGankAdapter.setOnRecyclerViewItemClickListener(new GankAdapter.OnRecyclerViewItemClickListener() {
@Override
public void clickItem(View view, int position) {
showBigImage(mGankList.get(position).getUrl());
}
});
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (!ViewCompat.canScrollVertically(recyclerView, 1)) {
mPresenter.getGank();
}
}
});
}
@Override
protected void initChildView(View mView, Bundle b) {
mGankList=new ArrayList<>();
mRecyclerView= (RecyclerView) mView.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));
mGankAdapter=new GankAdapter(mGankList,getContext());
mRecyclerView.setAdapter(mGankAdapter);
}
@Override
protected int getLayoutId() {
return R.layout.activity_dagger;
}
@Override
public void showGank(GankPictureBean mGank) {
mGankList.addAll(mGank.getResults());
mGankAdapter.notifyDataSetChanged();
}
@Override
public void showBigImage(String url) {
BigImageDialog bigImageDialog=new BigImageDialog(getContext(),R.style.Dialog,url);
bigImageDialog.show();
}
}

效果图

Tags: Android
使用微信添加

若你觉得我的文章对你有帮助,请添加我为好友

扫描二维码,分享此文章